/**
 *
 */
package com.storm.lib.template;

import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import com.storm.lib.base.BaseParameter;
import com.storm.lib.bean.RoleIntParameter;
import com.storm.lib.po.TimerPo;
import com.storm.lib.service.TimerService;
import com.storm.lib.type.DateType;
import com.storm.lib.type.TimerType;
import com.storm.lib.util.DateUtil;
import com.storm.lib.util.ExceptionUtil;
import com.storm.lib.util.ParameterUtil;



/**
 * 类功能: 定时器操作类
 * @author johnny
 * @version 2010-11-25
 */
@Component
public class TimerTemplate {
	
	/**
	 * 定时器类的Cache,key是时间戳
	 */
	private static ConcurrentHashMap<Long, List<TimerPo>> timerCache;
	

	
	protected final Logger logger = Logger.getLogger(getClass());

	@Autowired
	protected TimerService timerService;


	public  void initTimerCache(){
		timerCache = new ConcurrentHashMap();
	}
	
	public ConcurrentHashMap<Long, List<TimerPo>> getTimerMap(){
		if(timerCache==null){
			initTimerCache();
		}
		return timerCache;
	}

	/**
	 *
	 * 方法功能:将所有记录加载到内存
	 * 更新时间:2010-11-29, 作者:johnny
	 */
	public void loadTimerCache(){
		logger.debug("加载定时器到内存");
	}

	/**
	 *
	 * 方法功能:插入一个定时任务
	 * 更新时间:2010-11-25, 作者:johnny
	 */
	public Integer insertTimer(long endTime,int timerType,BaseParameter param){
		TimerPo timerPo = new TimerPo();
		timerPo.setStartTime(DateUtil.getCurrentTimeStamp());
		timerPo.setEndTime(DateUtil.getTimeStamp(endTime));
		timerPo.setTimerType((short)timerType);
		timerPo.setState((short)TimerType.TIMER_STATE_WAIT);
		timerPo.setParameters(param.toString());
		timerPo = (TimerPo) timerService.createTimer(timerPo);
		Object obj = getTimerMap().get(endTime);
		List<TimerPo> theItems = null;
		if(obj==null){
			theItems = Collections.synchronizedList(new ArrayList<TimerPo>());
			logger.debug("创建时间节点目录:"+endTime+" 对应时间:"+new Timestamp(endTime).toLocaleString());
		}
		else{
			theItems = (List<TimerPo>) obj;
		}
		theItems.add(timerPo);
		getTimerMap().put(endTime, theItems);
		logger.debug("添加时间项:"+endTime+" 对应时间:"+new Timestamp(endTime).toLocaleString());
		return timerPo.getId();
	}



	/**
	 *
	 * 方法功能:移除一个定时任务
	 * 更新时间:2010-11-25, 作者:johnny
	 */
	public void removeTimer(int timerId,long endTime){
		List<TimerPo> theItems = null;
		Object obj = getTimerMap().get(endTime);
		if(obj==null){
			logger.debug("移出失败,没有发现时间节点目录:"+endTime+" 对应时间:"+new Timestamp(endTime).toLocaleString());
		}
		else{
			theItems = (List<TimerPo>) obj;
			int itemIndex = -1;
			for (int i = 0; i < theItems.size(); i++) {
				TimerPo timerPo = theItems.get(i);
				if(timerPo.getId()==timerId){
					itemIndex = i;
					break;
				}
			}
			if(itemIndex!=-1){
				theItems.remove(itemIndex);
//				getTimerMap().put(endTime, theItems);
				logger.debug("移出时间项:"+timerId+" 对应时间:"+new Timestamp(endTime).toLocaleString());
				if(theItems.size()==0){
					getTimerMap().remove(endTime);
					logger.debug("时间节点目录为空,移除:"+timerId+" 对应时间:"+new Timestamp(endTime).toLocaleString());
				}
			}
			else{
				logger.debug("未找到时间项:"+timerId+" 对应时间:"+new Timestamp(endTime).toLocaleString());
			}
		}
	}

	/**
	 *
	 * 方法功能:移除一个定时任务
	 * 更新时间:2010-11-25, 作者:johnny
	 */
	public void removeTimer(int timerId){
		ConcurrentHashMap<Long, List<TimerPo>> map =getTimerMap();

//		Set keys=map.keySet();
		Iterator iter = map.entrySet().iterator();
		while (iter.hasNext()) {
			Map.Entry entry = (Map.Entry) iter.next();
			Long key = (Long) entry.getKey();
			List<TimerPo> theItems = (List<TimerPo>) entry.getValue();
			for (int i = 0; i < theItems.size(); i++) {
				TimerPo timerPo = theItems.get(i);
				if(timerPo.getId()==timerId){
					theItems.remove(i);
//					getTimerMap().put(endTime, theItems);
					logger.debug("移出时间项:"+timerId+" 对应时间:"+new Timestamp(key).toLocaleString());
					if(theItems.size()==0){
						map.remove(key);
						logger.debug("时间节点目录为空,移除:"+timerId+" 对应时间:"+new Timestamp(key).toLocaleString());
					}
					return;
				}
			}
			logger.debug("移除失败,没有找到对应项:"+timerId);
		}
	}

	/**
	 *
	 * 方法功能:定时任务加速
	 * 更新时间:2010-11-25, 作者:johnny
	 * @param timerId 定时器编号
	 * @param seconds 秒数
	 */
	public void reduceTimerSeconds(int timerId,long endTime,int seconds){
		List<TimerPo> theItems = null;
		Object obj = getTimerMap().get(endTime);
		if(obj==null){
			logger.debug("加速失败,没有发现时间节点目录:"+endTime+" 对应时间:"+new Timestamp(endTime).toLocaleString());
		}
		else{
			theItems = (List<TimerPo>) obj;
			int itemIndex = -1;
			for (int i = 0; i < theItems.size(); i++) {
				TimerPo timerPo = theItems.get(i);
				if(timerPo.getId()==timerId){
					itemIndex = i;
					long targetTime = DateUtil.reduceTime(endTime, DateType.TIME_TYPE_SECOND, seconds);
					if(targetTime<=System.currentTimeMillis()){
						activeTimerNow(timerId);
					}
					else{
						getTimerMap().put(endTime, theItems);
						logger.debug("加速时间项:"+timerId+" 原来对应时间:"+new Timestamp(endTime).toLocaleString()+ " 之后:"+timerPo.getEndTime().toLocaleString());
						break;
					}
				}
			}
			if(itemIndex!=-1){
			}
			else{
				logger.debug("未找到时间项:"+timerId+" 对应时间:"+new Timestamp(endTime).toLocaleString());
			}
		}
	}

	/**
	 * 方法功能:立即更新
	 * 更新时间:2010-11-25, 作者:johnny
	 * @param timerId
	 */
	public void activeTimerNow(int timerId) {
		executeTimer(timerId);
	}

	/**
	 * 方法功能:执行定时器
	 * 更新时间:2010-11-25, 作者:johnny
	 * @param timerId
	 */
	private void executeTimer(int timerId) {
		logger.debug("执行定时器 "+timerId);
		removeTimer(timerId);
		timerService.executeTimer(timerId);
	}

	/**
	 *
	 * 方法功能:定时任务延长
	 * 更新时间:2010-11-25, 作者:johnny
	 * @param timerId 定时器编号
	 * @param seconds 秒数
	 */
	private void addTimerSeconds(int timerId,long endTime,int seconds){
		List<TimerPo> theItems = null;
		Object obj = getTimerMap().get(endTime);
		if(obj==null){
			logger.debug("延长失败,没有发现时间节点目录:"+endTime+" 对应时间:"+new Timestamp(endTime).toLocaleString());
		}
		else{
			theItems = (List<TimerPo>) obj;
			int itemIndex = -1;
			for (int i = 0; i < theItems.size(); i++) {
				TimerPo timerPo = theItems.get(i);
				if(timerPo.getId()==timerId){
					itemIndex = i;
					timerPo.setEndTime(DateUtil.getTimeStamp(DateUtil.addTime(endTime, DateType.TIME_TYPE_SECOND, seconds)));
					getTimerMap().put(endTime, theItems);
					logger.debug("延长时间项:"+timerId+" 原来对应时间:"+new Timestamp(endTime).toLocaleString()+ " 之后:"+timerPo.getEndTime().toLocaleString());
					break;
				}
			}
			if(itemIndex!=-1){
			}
			else{
				logger.debug("未找到时间项:"+timerId+" 对应时间:"+new Timestamp(endTime).toLocaleString());
			}
		}
	}

	/**
	 *
	 * 更新时间:2010-11-29, 作者:johnny
	 * 方法功能:激活比指定时间早的定时器
	 * @param time
	 */
	public void activePassedTimer(long time) {
//		logger.debug("正在寻找比"+DateUtil.getText(time)+"之前的定时器");
		Set<Long> sets= getTimerMap().keySet();
	    Object[] keys  = sets.toArray();
        Arrays.sort(keys);
        List<TimerPo> timerPos = Collections.synchronizedList(new ArrayList<TimerPo>());
		for (int i=0;i<keys.length;i++) {
			Long timerTime = (Long) keys[i];
			if(timerTime<=time){
				List<TimerPo> theList = getTimerMap().get(timerTime);
				if(theList==null){
					ExceptionUtil.throwInvalidParamException();
				}
				for (int j = 0; j < theList.size(); j++) {
					timerPos.add(theList.get(j));
				}
			}
		}
		for (int i = 0; i < timerPos.size(); i++) {
			TimerPo timerPo = timerPos.get(i);
			activeTimerNow(timerPo.getId());
		}
	}

	/**
	 * 方法功能:获得Timer参数
	 * 更新时间:2011-1-11, 作者:johnny
	 * @param timerPo
	 * @return
	 */
	public RoleIntParameter getTimerRoleIntParameter(TimerPo timerPo) {
//		BaseTimer baseTimer = timerService.getTimerByType(timerPo.getTimerType());
		RoleIntParameter roleIntParameter = (RoleIntParameter)ParameterUtil.getParameter(timerPo.getParameters());
		return roleIntParameter;
	}

	/**
	 * 方法功能:找到Timer
	 * 更新时间:2011-1-11, 作者:johnny
	 * @param timerId
	 * @return
	 */
	public TimerPo findTimer(Integer timerId) {
		return timerService.findTimer(timerId);
	}
	
	public void syncTimer(TimerPo timerPo){
		timerService.syncTimer(timerPo);
	}
	
	
}
